using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using GeneratorLibrary.Client.Base;
using MySql.Data.MySqlClient;

namespace MySqlGeneratorLibrary {
    public class MySqlClassColumn : ClassColumnBase {
        MySqlDbType sqlDataType;

        public MySqlClassColumn(DataRow dr) : base(dr) { }

        protected override string getDotNetDataType(ref string DbDataType) {
            switch (DbDataType.ToLower()) {
                case "bigint":
                    if (isPrimaryKey || (isForeignKey && !isNullable))
                        nullValue = "0";
                    return "long" + (isNullable ? "?" : "");
                case "binary":
                case "image":
                case "timestamp":
                case "varbinary":
                    return "byte[]";
                case "bit":
                    return "bool" + (isNullable ? "?" : "");
                case "char":
                case "nchar":
                case "ntext":
                case "text":
                case "nvarchar":
                case "varchar":
                case "xml":
                    return "string";
                case "datetime":
                case "smalldatetime":
                case "date":
                case "time":
                case "datetime2":
                case "datetimeoffset":
                    return "DateTime" + (isNullable ? "?" : "");
                case "decimal":
                case "money":
                case "smallmoney":
                    return "decimal" + (isNullable ? "?" : "");
                case "float":
                    return "float" + (isNullable ? "?" : "");
                case "int":
                    if (isPrimaryKey || (isForeignKey && !isNullable))
                        nullValue = "0";
                    return "int" + (isNullable ? "?" : "");
                case "real":
                    return "double" + (isNullable ? "?" : "");
                case "uniqueidentifier":
                    return "Guid";
                case "smallint":
                    if (isPrimaryKey || (isForeignKey && !isNullable))
                        nullValue = "0";
                    return "short" + (isNullable ? "?" : "");
                case "tinyint":
                    if (isPrimaryKey || (isForeignKey && !isNullable))
                        nullValue = "0";
                    return "byte" + (isNullable ? "?" : "");
                case "variant":
                case "sql_variant":
                    DbDataType = "Variant";
                    return "object";
                case "udt":
                case "structured":
                    return "object";
                case "numeric":
                    DbDataType = "Decimal";
                    return "decimal" + (isNullable ? "?" : ""); 
            }
            return null;
        }

        protected override void generate() {
            if (isPrimaryKey && isIdentity) {
                memberName = "id";
                propertyName = "Id";
                extraMethod = "public bool IsNew() {\nreturn id == 0; \n}\n";
                allowsIDataModel = true;
            } else {
                memberName = columnName.Substring(0, 1).ToLower() + columnName.Remove(0, 1);
                propertyName = columnName.Substring(0, 1).ToUpper() + columnName.Remove(0, 1);
            }

            if (isNullable && nullValue != "null") {
                member = dataType + " " + memberName + " = " + nullValue + ";\n";
            } else {
                member = dataType + " " + memberName + ";\n";
            }
            property = "public " + dataType + " " + propertyName + " {\n" + "get { return " + memberName + "; }\nset{ " +
                memberName + " = value; }\n}\n";

            if (isPrimaryKey) {
                if (sqlDataType == MySqlDbType.Int32) {
                    if ((isNullable || isIdentity) && nullValue != "null") {
                        dacAttribute = "[PKMySqlColumn(\"" + columnName + "\", " + nullValue + ")]";
                    } else if (!isIdentity) {
                        dacAttribute = "[PKMySqlColumn(\"" + columnName + "\", " + isIdentity.ToString() + ")]";
                    } else {
                        dacAttribute = "[PKMySqlColumn(\"" + columnName + "\")]";
                    }
                } else {
                    dacAttribute = "[PKMySqlColumn(\"" + columnName + "\", MySqlDbType." + Enum.GetName(typeof(MySqlDbType), sqlDataType)
                        + ", " + nullValue + ")]";
                }
            } else if (isIdentity) {
                if (sqlDataType == MySqlDbType.Int32) {
                    if (nullValue != "null")
                        dacAttribute = "[IdentityNotPKMySqlColumn(\"" + columnName + "\", " + nullValue + ")]";
                    else
                        dacAttribute = "[IdentityNotPKMySqlColumn(\"" + columnName + "\")]";
                } else {
                    dacAttribute = "[IdentityNotPKMySqlColumn(\"" + columnName + "\", MySqlDbType." + Enum.GetName(typeof(MySqlDbType), sqlDataType)
                        + ", " + nullValue + ")]";
                }
            } else if (sqlDataType == MySqlDbType.VarChar) {
                if (isNullable && nullValue != "null") {
                    dacAttribute = "[StringMySqlColumn(\"" + columnName + "\", " + nullValue + ")]";
                } else {
                    dacAttribute = "[StringMySqlColumn(\"" + columnName + "\")]";
                }
            } else {
                if (isNullable && nullValue != "null") {
                    dacAttribute = "[MySqlColumn(\"" + columnName + "\", MySqlDbType." + Enum.GetName(typeof(MySqlDbType), sqlDataType)
                        + ", " + nullValue + ")]";
                } else {
                    dacAttribute = "[MySqlColumn(\"" + columnName + "\", MySqlDbType." + Enum.GetName(typeof(MySqlDbType), sqlDataType) + ")]";
                }
            }
        }

        protected override void setDbDataType(string DbDataType) {
            try {
                sqlDataType = (MySqlDbType)Enum.Parse(typeof(MySqlDbType), DbDataType, true);
            } catch {
                throw new Exception("Currently, this program is not set up to deal with columns of type '" + DbDataType + "'. Column = " + columnName);
            }
        }
        public override string GetDotNetDefaultCoalesce() {

            switch (sqlDataType) {
                case MySqlDbType.Int16:
                case MySqlDbType.Int24:
                case MySqlDbType.Int32:
                case MySqlDbType.Int64:
                case MySqlDbType.UInt16:
                case MySqlDbType.UInt24:
                case MySqlDbType.UInt32:
                case MySqlDbType.UInt64:
                case MySqlDbType.Decimal:
                case MySqlDbType.Float:
                case MySqlDbType.Byte:
                case MySqlDbType.Double:
                    return "0";
                case MySqlDbType.Date:
                    return "DateTime.Now.Date";
                case MySqlDbType.DateTime:
                    return "DateTime.Now";
                case MySqlDbType.Time:
                    return "DateTime.Now.TimeOfDay";
                default:
                    if (dataType.ToLower() == "string")
                        return "string.Empty";
                    else
                        return "";
            }

            switch (DataType.ToLower()) {
                case "bigint":
                case "decimal":
                case "money":
                case "smallmoney":
                case "float":
                case "int":
                case "real":
                case "smallint":
                case "numeric":
                case "tinyint":
                    return "0";
                case "bit":
                    return "2";
                case "datetime":
                case "smalldatetime":
                case "date":
                case "time":
                case "datetime2":
                case "datetimeoffset":
                    return "getdate()";
                default:
                    return "''";
            }
            return null;
        }
    }
}
